#include "generator.h"
#include <qmath.h>
#include <QFile>
#include <qendian.h>
Generator::Generator(AVStream *pAVStream,AVCodec *pAVCodec)
  :  m_pos(0)
{

    m_pAVCodec = pAVCodec;

    m_pFrame = avcodec_alloc_frame();

    audio_clock  = 0;

    m_pAVStream   = pAVStream;

    audio_buf_size =   0;

    audio_buf_index=   0;


    //Out Audio Param
    uint64_t out_channel_layout=AV_CH_LAYOUT_STEREO;//AV_CH_LAYOUT_STEREO;

    int out_nb_samples=m_pAVStream->codec->frame_size;

    AVSampleFormat out_sample_fmt= AV_SAMPLE_FMT_S16;

    int out_sample_rate=m_pAVStream->codec->sample_rate;

    qDebug(QString("out_sample_rate  :").append(QString::number(out_sample_rate)).toLocal8Bit().data());

    qDebug(QString("out_nb_samples  :").append(QString::number(out_nb_samples)).toLocal8Bit().data());

    int out_channels=av_get_channel_layout_nb_channels(out_channel_layout);
    //Out Buffer Size
    out_buffer_size=av_samples_get_buffer_size(NULL,out_channels ,out_nb_samples,out_sample_fmt, 1);//BUF 大小

    au_convert_ctx = swr_alloc();

    int64_t in_channel_layout=av_get_default_channel_layout(m_pAVStream->codec->channels);

    au_convert_ctx=swr_alloc_set_opts(au_convert_ctx,out_channel_layout, out_sample_fmt, out_sample_rate,
            in_channel_layout,m_pAVStream->codec->sample_fmt , m_pAVStream->codec->sample_rate,0, NULL);

    swr_init(au_convert_ctx);

    out_buffer  =(uint8_t *)av_malloc(192000*2);
//    QFile inputFile;

//    inputFile.setFileName(strFile);

//    inputFile.open(QIODevice::ReadOnly);

//    m_buffer = QByteArray(inputFile.readAll());
//    inputFile.close();
}

Generator::~Generator()
{
    if(m_pFrame)
    {
         av_free(m_pFrame);
         m_pFrame = 0;
    }

    if(au_convert_ctx)
    {
        swr_free(&au_convert_ctx);
    }

    if(out_buffer)
    {
        av_free(out_buffer);
    }
}

void Generator::appendAudioPacket(const AVPacket &aVpkt1)
{
    CCriticalAutoLock loAutoLock(oCriSection);

    m_AVPacketList.push(aVpkt1);
}

bool Generator::PopAudioPacket(AVPacket &aVpkt1)
{
    CCriticalAutoLock loAutoLock(oCriSection);

    if(!m_AVPacketList.empty())
    {
        aVpkt1 = m_AVPacketList.front();
        m_AVPacketList.pop();
        return  true;
    }else
    {
        return  false;
    }
}

void Generator::start()
{
    open(QIODevice::ReadOnly);
}

void Generator::stop()
{
    m_pos = 0;
    close();
}

qint64 Generator::bytesAvailable() const
{
    return m_buffer.size() + QIODevice::bytesAvailable();
}

double Generator::get_audio_clock()
{
    double pts;
    int hw_buf_size, bytes_per_sec, n;

    pts = audio_clock; // maintained in the audio thread
    hw_buf_size = audio_buf_size - audio_buf_index;
    bytes_per_sec = 0;
    n = m_pAVStream->codec->channels * 2;
    if (m_pAVStream)
    {
        bytes_per_sec = m_pAVStream->codec->sample_rate * n;
    }
    if (bytes_per_sec)
    {
        pts -= (double)hw_buf_size / bytes_per_sec;
    }
    return pts;
}

int Generator::audio_decode_frame()
{
    int ret, got_picture, n;

    AVPacket  pkt ;

    memset(&pkt,0,sizeof(AVPacket));

    for (;;)
    {
        while (pkt.size != 0)
        {
            got_picture = 0;

            ret = avcodec_decode_audio4(m_pAVStream->codec, m_pFrame, &got_picture, &pkt);

            if ( ret < 0 )
            {
                int a= 0;
            }

            if ( got_picture > 0 )
            {
                memset(out_buffer, 0 , 192000*2);

                swr_convert(au_convert_ctx,&out_buffer, 192000,(const uint8_t **)m_pFrame->data , m_pFrame->nb_samples);
            }else
            {
                if (pkt.data)
                    av_free_packet(&pkt);
                continue;
            }

            n = 2 * m_pAVStream->codec->channels;

            audio_clock += (double)out_buffer_size / (double)(n * m_pAVStream->codec->sample_rate);

            return out_buffer_size;
        }

        if (pkt.data)
            av_free_packet(&pkt);

        bool bRet = PopAudioPacket(pkt);

        if(bRet == false)  //没数据包了
        {
            return -1;
        }

        if (pkt.pts != AV_NOPTS_VALUE)
        {
            audio_clock = av_q2d(m_pAVStream->time_base) * pkt.pts;
        }
    }
}
qint64 Generator::readData(char *data, qint64 len)
{
    //qDebug(QString("readData len size:").append(QString::number(len)).toLocal8Bit().data());
    int lenOld = len;
    int len1, audio_size;
    while (len > 0)
    {
        if (audio_buf_index == audio_buf_size)
        {
            // We have already sent all our data; get more
            audio_size = audio_decode_frame();//继续解码处理 并 返回buf大小

            if (audio_size < 0)
            {
                // If error, output silence
                audio_buf_size = 1024;

                memset(out_buffer, 0 , audio_buf_size);
            }
            else
            {
                audio_buf_size = audio_size;
            }

            audio_buf_index = 0;
        }
        len1 = audio_buf_size - audio_buf_index;

        if (len1 > len)
            len1 = len;
        memcpy(data, (uint8_t *)out_buffer + audio_buf_index, len1);
        len -= len1;
        data += len1;
        audio_buf_index += len1;
    }
    return lenOld;
}

qint64 Generator::writeData(const char *data, qint64 len)
{
    Q_UNUSED(data);
    Q_UNUSED(len);

    return 0;
}

